package GitObjController

import (
	"arabApi/app/api/controllers"
	"arabApi/app/api/controllers/CFun"
	"arabApi/app/api/services/ObjGitService"
	"arabApi/pkg/helpers"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"os/exec"
	"strings"
)

type Exec struct {
	controllers.BaseAPIController
}

// 0 创建分支 1 提交 2 发布测试 3 发布预发布 4 发布正式
func (Exec) Gitnext(c *gin.Context) {

	id := c.DefaultQuery("id", "1")
	pathIds := c.Query("pathIds")
	pathIdss := strings.Split(pathIds, ",")

	// 分支信息
	msg := ObjGitService.BranchMsgByID(id)
	obid := msg.ObId

	// 项目信息
	objPathStruct := ObjGitService.MsgByID(cast.ToString(obid))

	step := msg.Step
	// 发送分支信息
	objPath := objPathStruct.JobPath
	barch := msg.Branch

	// 对比分支差异
	var _ *exec.Cmd

	if step == 1 {
		if ok, err := Step1(objPath, barch); ok != true {
			CFun.Ajax_return_fail(c, CFun.WithMsg(err))
			return
		}
	} else if step == 2 { // 发布测试环境
		if ok, err := Step2(objPath, barch, objPathStruct.JobType, pathIdss); ok != true {
			CFun.Ajax_return_fail(c, CFun.WithMsg(err))
			return
		}
	} else if step == 3 { // 发布预发布环境
		other := ObjGitService.BranchMsgByStep(objPathStruct.ID)
		if len(other) > 0 {
			CFun.Ajax_return_fail(c, CFun.WithMsg("有其他项目待发布"))
			return
		}
		if ok, err := Step3(objPath, barch, objPathStruct.JobType, pathIdss); ok != true {
			CFun.Ajax_return_fail(c, CFun.WithMsg(err))
			return
		}
	} else if step == 4 {
		if ok, err := Step4(objPath, barch, objPathStruct.JobType, pathIdss); ok != true {
			CFun.Ajax_return_fail(c, CFun.WithMsg(err))
			return
		}
	} else {
		CFun.Ajax_return_success(c, CFun.WithMsg("步骤错误"))
		return
	}

	//if err := ObjGitService.EditBranchStep(id, cast.ToInt(msg.NextStep)); err != nil {
	if err := ObjGitService.EditBranchStep(id, cast.ToInt(step+1)); err != nil {
		CFun.Ajax_return_success(c, CFun.WithMsg("修改失败"))
		return
	}
	CFun.Ajax_return_success(c, CFun.WithMsg("成功"))

}

func Step0(objpath, branch string) (bool, string) {
	if ok, str := checkBranchAndPull(objpath, branch); !ok {
		return false, "拉去分支失败" + str
	}

	if ok := checkBranchB(branch, objpath); !ok {
		return false, "切换分支B失败"
	}
	if ok := checkBranch("dev", objpath); !ok {
		//CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支失败2"))
		return false, "切换分支失败2"
	}
	if ok := checkBranchB(branch+"_copy", objpath); !ok {
		//CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支b_copy失败"))
		return false, "切换分支b_copy失败"
	}

	return true, ""
}

func checkBranchAndPull(objpath, branch string) (bool, string) {
	if ok := checkBranch(branch, objpath); !ok {
		return false, "切换分支失败1"
	}
	if ok, str := gitPull(branch, objpath); !ok {
		return false, "拉去分支失败" + str
	}

	return true, ""
}

func Step1(objpath, branch string) (bool, string) {

	if ok, str := checkBranchAndPull(objpath, branch); !ok {
		return false, "拉去分支失败" + str
	}

	err, s := checkDiff1(objpath, branch)
	if err != nil {
		return false, "diff 失败 1-3" + err.Error()
	}
	return true, s
}

func Step2(objpath, branch, objType string, pathIdss []string) (bool, string) {
	if ok, str := checkBranchAndPull(objpath, branch); !ok {
		return false, "拉去分支失败" + str
	}

	if ok, err := PushJobS(objType, objpath, pathIdss); ok != true {
		return false, "发送代码失败" + err
	}

	return true, ""
}

func Step3(objPath, branch, objType string, pathIdss []string) (bool, string) {
	if ok, str := checkBranchAndPull(objPath, branch); !ok {
		return false, "拉去分支失败" + str
	}

	// 切换分支
	if ok := checkBranch("qa", objPath); !ok {
		return false, "切换分支失败"
	}

	// 合并代码
	if ok, str := gitMerge(objPath, branch); !ok {
		return false, "合并分支失败" + str
	}

	// 检测合并冲突
	err1, str := checkmerge()
	if err1 != nil {
		return false, err1.Error()
	}
	if len(str) != 0 {
		return false, "代码有更新，需要合并" + str
	}

	if err3, str1 := gitCommit(objPath); err3 == false {
		return false, str1
	}

	////// 合并提交
	if ok, str := gitPush(objPath, "qa"); !ok {
		return false, "qa 提交失败" + str
	}

	if ok, err := PushJobS(objType, objPath, pathIdss); ok != true {
		return false, "发送代码失败" + err
	}

	return true, ""

}

func Step4(objPath, barch, objType string, pathIdss []string) (bool, string) {
	if ok, str := checkBranchAndPull(objPath, "dev"); !ok {
		return false, "拉去分支失败" + str
	}

	// 切换分支
	//if ok := checkBranch("dev", objPath); !ok {
	//	return false, "切换分支失败"
	//}
	////

	// 检测合并冲突
	err2, str := gitMerge(objPath, "qa")
	if !err2 {
		return false, str
	}
	// 检测合并冲突
	err1, str := checkmerge()
	if err1 != nil {
		return false, err1.Error()
	}
	if len(str) != 0 {
		return false, "代码有更新，需要合并" + str
	}

	if err3, str1 := gitCommit(objPath); err3 == false {
		return false, str1
	}

	////// 合并提交
	if ok, str := gitPush(objPath, "dev"); !ok {
		return false, "dev 提交失败" + str
	}

	if ok, err := PushJobSDev(objType, objPath, pathIdss); ok != true {
		return false, "发送代码失败" + err
	}

	return true, ""
}

func (Exec) Back(c *gin.Context) {

	id := c.DefaultQuery("id", "1")
	msg := ObjGitService.BranchMsgByID(id)
	//barch := msg.Branch
	step := msg.Step
	objPathStruct := ObjGitService.MsgByID(cast.ToString(msg.ObId))
	objPath := objPathStruct.JobPath

	if step == 5 || step == 6 {
		CFun.Ajax_return_fail(c, CFun.WithMsg("已经发布线上"))
		return
	}

	if step == 4 {
		// 切换分支
		if ok := checkBranch("qa", objPath); !ok {
			CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支失败"))
			return
		}
		// 切换分支
		if ok, str := gitBack(); !ok {
			CFun.Ajax_return_fail(c, CFun.WithMsg("打回失败"+str))
			return
		}

		// 切换分支
		if ok, str := gitStash(); !ok {
			CFun.Ajax_return_fail(c, CFun.WithMsg("打回失败"+str))
			return
		}

	}
	if err := ObjGitService.EditBranchStep(id, 1); err != nil {
		CFun.Ajax_return_fail(c, CFun.WithMsg("修改step 失败"+err.Error()))
		return
	} else {
		CFun.Ajax_return_success(c)
		return
	}

}

func PushJobS(JobType, objPath string, pathIdss []string) (bool, string) {
	if JobType == "vue" {
		if ok, str := vue_build(objPath); !ok {
			//CFun.Ajax_return_fail(c, CFun.WithMsg("vue 打包失败"+str))
			return false, "vue 打包失败" + str
		}
		objPath = objPath + "/dist"
	} else if JobType == "go" {
		if ok, str := go_build(objPath); !ok {
			return false, "vue 打包失败" + str
		}
		objPath = objPath + "/arabApi"
	}

	for _, v := range pathIdss {
		pushPath := ObjGitService.PathMsgByID(cast.ToString(v))
		if JobType == "go" {
			killPort(pushPath.Path)
		}
		pushJonToPath1(objPath, pushPath.Path)
		if JobType == "go" {
			jobstart(objPath)
		}
	}

	return true, ""

}

func PushJobSDev(JobType, objPath string, pathIdss []string) (bool, string) {
	if JobType == "vue" {
		if ok, str := vue_build(objPath); !ok {
			//CFun.Ajax_return_fail(c, CFun.WithMsg("vue 打包失败"+str))
			return false, "vue 打包失败" + str
		}
		objPath = objPath + "/dist"
	} else if JobType == "go" {
		if ok, str := go_build(objPath); !ok {
			return false, "vue 打包失败" + str
		}
		objPath = objPath + "/arabApi"
	}

	for _, v := range pathIdss {
		pushPath := ObjGitService.PathMsgByID(cast.ToString(v))

		pushJonToPath1(objPath, pushPath.Path)
		if JobType == "go" {
			ok, port := goPort(objPath)
			if ok == false {
				return false, port
			}

			newPort := ""
			if cast.ToInt(port)%10 == 1 {
				newPort = "8100"
			} else {
				newPort = "8101"
			}
			
			upGoPort(pushPath.Path, port, newPort)

			killPort(pushPath.Path)

			// 启动项目
			jobstart(objPath)
			upNginx(port, newPort)
		}

	}

	return true, ""

}

func NewBranch(branch string, id string, objpath string) (code bool, msg string) {
	if ok := checkBranch("dev", objpath); !ok {
		return false, "切换分支失败1"
	}
	if ok, str := gitPull("dev", objpath); !ok {
		return false, "拉去分支失败" + str
	}

	if ok := checkBranchB(branch, objpath); !ok {
		//CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支B失败"))
		return false, "切换分支B失败"
	}
	if ok := checkBranch("dev", objpath); !ok {
		//CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支失败2"))
		return false, "切换分支失败2"
	}
	if ok := checkBranchB(branch+"_copy", objpath); !ok {
		//CFun.Ajax_return_fail(c, CFun.WithMsg("切换分支b_copy失败"))
		return false, "切换分支b_copy失败"
	}

	return true, ""
}

func checkDiff1(objpath, barch string) (error, string) {
	cmd := exec.Command("/home/obj/sshobj/diffBarnch.sh", objpath, barch+"_copy", barch)
	fmt.Println("/home/obj/sshobj/diffBarnch.sh", objpath, barch+"_copy", barch)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return err, ""
	}
	if len(out) != 0 && string(out) != "master\n"+barch+"_copy\n\n" {
		return nil, string(out)
	}

	return nil, ""
}

func checkmerge() (error, string) {
	cmd := exec.Command("/home/obj/sshobj/ct.sh")
	fmt.Println("/home/obj/sshobj/ct.sh")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return err, ""
	}
	if len(out) != 0 {
		return nil, string(out)
	}
	return nil, ""
}

func getBranch() string {
	cmd := exec.Command("/home/obj/sshobj/getBranch.sh")
	fmt.Println("/home/obj/sshobj/getBranch.sh")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return ""
	}
	return strings.Trim(cast.ToString(out), "\n")
}

func gitMerge(objPath, branch string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitMerge.sh", objPath, branch)
	fmt.Println("/home/obj/sshobj/gitMerge.sh", objPath, branch)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}

}

func gitPush(objPath, branch string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitPush.sh", objPath, branch)
	fmt.Println("/home/obj/sshobj/gitPush.sh", objPath, branch)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func gitPull(branch, objpath string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitPull.sh", branch, objpath)
	fmt.Println("/home/obj/sshobj/gitPull.sh", branch, objpath)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func checkBranch(branch, objPath string) bool {
	tbranch := getBranch()
	if branch != tbranch {
		cmd := exec.Command("/home/obj/sshobj/gitBranch.sh", branch, objPath)
		fmt.Println("/home/obj/sshobj/gitBranch.sh", branch, objPath)
		_, err := cmd.CombinedOutput()
		helpers.EchoStr(err)
		if err != nil {
			return false
		} else {
			return true
		}
	} else {
		return true
	}
}

// 创建并且切换分支
func checkBranchB(branch, jobpath string) bool {
	cmd := exec.Command("/home/obj/sshobj/gitBranchB.sh", branch, jobpath)
	fmt.Println("/home/obj/sshobj/gitBranchB.sh", branch, jobpath)
	_, err := cmd.CombinedOutput()
	if err != nil {
		return false
	} else {
		return true
	}
}

func getMsg() (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/msg.sh")
	fmt.Println("/home/obj/sshobj/msg.sh")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, ""
	} else {
		return true, cast.ToString(out)
	}
}

func pushJonToPath1(jobPath, path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/pushJonToPath.sh", jobPath, path)
	fmt.Println("/home/obj/sshobj/pushJonToPath.sh", jobPath, path)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func killPort(port string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/netkill.sh", port)
	fmt.Println("/home/obj/sshobj/netkill.sh", port)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func upGoPort(path, oldPort, newPort string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/upGoPort.sh", path, oldPort, newPort)
	fmt.Println("/home/obj/sshobj/upGoPort.sh", path, oldPort, newPort)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func goPort(path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/getGoJobPort.sh", path)
	fmt.Println("/home/obj/sshobj/getGoJobPort.sh", path)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func jobstart(path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/jobstart.sh", path)
	fmt.Println("/home/obj/sshobj/jobstart.sh", path)
	err := cmd.Run()
	if err != nil {
		return false, err.Error()
	} else {
		return true, ""
	}
}
func upNginx(oldPort, newPort string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/upNginx.sh", oldPort, newPort)
	fmt.Println("/home/obj/sshobj/upNginx.sh", oldPort, newPort)
	err := cmd.Run()
	if err != nil {
		return false, err.Error()
	} else {
		return true, ""
	}
}

func gitBack() (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitBack.sh")
	fmt.Println("/home/obj/sshobj/gitBack.sh")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func gitStash() (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitStash.sh")
	fmt.Println("/home/obj/sshobj/gitStash.sh")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func ex_table(out string) []string {

	ss := cast.ToString(out)
	data := strings.Split(ss, "\n")

	list := make([]string, len(data))
	i1 := 0
	for _, v := range data {
		list[i1] = v
		i1++
	}
	return list
}

func vue_build(job_path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/vueBuild.sh", job_path)
	fmt.Println("/home/obj/sshobj/vueBuild.sh", job_path)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, ""
	} else {
		return true, cast.ToString(out)
	}
}

func go_build(job_path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/goBuild.sh", job_path)
	fmt.Println("/home/obj/sshobj/goBuild.sh", job_path)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, ""
	} else {
		return true, cast.ToString(out)
	}
}

func gitAdd() (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitAdd.sh")

	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func gitCommit(objPath string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/gitCommit.sh", objPath)
	fmt.Println("/home/obj/sshobj/gitCommit.sh", objPath)
	out, err := cmd.CombinedOutput()
	return true, cast.ToString(out)
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}

func checkDiff(barch string) (error, string) {
	cmd := exec.Command("/home/obj/sshobj/diffBarnch.sh", "dev", barch+"_copy")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return err, ""
	}
	if len(out) != 0 && string(out) != "master\n"+barch+"_copy\n\n" {
		return nil, string(out)
	}

	return nil, ""
}

func pushJonToPath(path string) (bool, string) {
	cmd := exec.Command("/home/obj/sshobj/pushJonToPath.sh", path)
	fmt.Println("/home/obj/sshobj/pushJonToPath.sh", path)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, err.Error()
	} else {
		return true, cast.ToString(out)
	}
}
